# -*- coding: utf-8 -*-
"""
@File:    db.py
@Author:  jk.dong
@Desc:    各数据库的连接实例构建
"""
from dbutils.pooled_db import PooledDB
from docwork.config import RUN_CONF
from docwork import logging, os


class BaseDB:
    def __init__(self, username:str='', password:str='', address:str='', dbname:str='', port:int=3306):
        self.username = username
        self.password = password
        self.address = address
        self.dbname = dbname
        self.port = port
        if self.username == '' or self.password == '' or self.address == '':
            logging.warning("数据库配置项不全，请检查。")

    def _pool(self, *args, **kwargs):
        pass

    def get_pool(self):
        return self._pool(self.address, self.port, self.dbname, self.username, self.password)

    def reload_pool(self):
        # 针对pool connection exhaust异常情况，释放所有连接，重新加载
        pass

    # 关闭数据库游标对象和数据库连接对象
    @staticmethod
    def release_resource(conn, cursor=None, rollback=False):
        try:
            if cursor is not None:
                cursor.close()
            else:
                logging.info("Cursor is None.")
            if rollback:
                logging.info("Roll back the current database connection.")
                conn.rollback()
        finally:
            if conn is not None:
                conn.close()
                # logging.info("This connection from pool has been released")
            else:
                logging.error("Connection is None!!!")


class OracleDB(BaseDB):
    def _pool(self, address, port, dbname, username, password):
        import cx_Oracle
        os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.UTF8'
        # os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.ZHS16GBK'
        # cx_Oracle.STRING
        dsn = cx_Oracle.makedsn(host=address, port=int(port), service_name=dbname)
        pool = cx_Oracle.SessionPool(
            user=username,
            password=str(password),
            dsn=dsn,
            min=int(RUN_CONF["db-setting"]["initial_conn"]),
            max=int(RUN_CONF["db-setting"]["max_conn"]),
            increment=1
        )
        logging.info("====== DataBase: Oracle Initializing ======")
        return pool

    @staticmethod
    def get_conn(pool):
        return pool.acquire()

    @staticmethod
    def get_cursor(conn):
        if conn is None:
            return None
        return conn.cursor()


class MysqlDB(BaseDB):
    def _pool(self, address, port, dbname, username, password):
        import pymysql
        conn_kwargs = {'host': address, 'user': username, 'passwd': password, 'db': dbname, 'port': port,
                      'charset': "utf8mb4"}
        pool = PooledDB(pymysql, mincached=int(RUN_CONF["db-setting"]["initial_conn"]),
                        maxcached=10, maxconnections=int(RUN_CONF["db-setting"]["max_conn"]), **conn_kwargs)
        logging.info("====== DataBase: Mysql Initializing ======")
        return pool

    @staticmethod
    def get_conn(pool):
        return pool.connection(shareable=False)

    @staticmethod
    def get_cursor(conn):
        if conn is None:
            return None
        cu = conn.cursor()
        if cu is not None:
            cu.execute('SET NAMES utf8mb4;')
            cu.execute('SET CHARACTER SET utf8mb4;')
            cu.execute('SET character_set_connection=utf8mb4;')
        return cu


class DMsqlDB(BaseDB):
    def _pool(self, address, port, dbname, username, password, *options):
        conn_kwargs = {'server': address, 'user': username, 'password': password, 'port': port}
        logging.info("====== DataBase: 达梦 Initializing ======")
        return conn_kwargs

    @staticmethod
    def get_conn(pool):
        import dmPython
        return dmPython.connect(**pool)

    @staticmethod
    def get_cursor(conn):
        if conn is None:
            return None

        cu = conn.cursor()
        # if cu is not None:
        #     cu.execute('SET NAMES utf8mb4;')
        #     cu.execute('SET CHARACTER SET utf8mb4;')
        #     cu.execute('SET character_set_connection=utf8mb4;')
        return cu


class PostgresqlDB(BaseDB):
    """
    腾讯的TD-SQL是基于Postgresql，因此也使用Postgresql连接
    """
    def _pool(self, address, port, dbname, username, password, *options):
        import psycopg2
        conn_kwargs = {'host': address, 'user': username, 'password': password, 'database': dbname, 'port': port}
        pool = PooledDB(psycopg2, mincached=int(RUN_CONF["db-setting"]["initial_conn"]),
                        maxcached=10, maxconnections=int(RUN_CONF["db-setting"]["max_conn"]), **conn_kwargs)
        logging.info("====== DataBase: Postgresql Initializing ======")
        return pool

    @staticmethod
    def get_conn(pool):
        return pool.connection(shareable=False)

    @staticmethod
    def get_cursor(conn):
        if conn is None:
            return None
        return conn.cursor()
